home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / drivers2.zip / T7231.ASM < prev    next >
Assembly Source File  |  1992-01-05  |  26KB  |  1,008 lines

  1. t7231_version    equ    1
  2.   ifndef DAN
  3. DAN    equ    4            ; 4 seems to work best.
  4.   endif
  5.  
  6. ;
  7. ; Code that is common between T7231 implementations.
  8. ;
  9.  
  10. ; Ported from Tim Krauskopf's micnet.asm, an assembly language
  11. ; driver for the MICOM-Interlan NI5210, by Russell Nelson.  Any bugs
  12. ; are due to Russell Nelson.
  13. ; Updated to version 1.08 Feb. 17, 1989 by Russell Nelson.
  14. ; Updated to support 1500 byte MTU April 27, 1989 By Brad Clements.
  15. ; copied and modified to support t7231 LanPACER controller by AT&T
  16. ; June 1, 1991 by Mark Darby.
  17.  
  18. ; Copyright, 1988-90, Russell Nelson
  19.  
  20. ;   This program is free software; you can redistribute it and/or modify
  21. ;   it under the terms of the GNU General Public License as published by
  22. ;   the Free Software Foundation, version 1.
  23. ;
  24. ;   This program is distributed in the hope that it will be useful,
  25. ;   but WITHOUT ANY WARRANTY; without even the implied warranty of
  26. ;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27. ;   GNU General Public License for more details.
  28. ;
  29. ;   You should have received a copy of the GNU General Public License
  30. ;   along with this program; if not, write to the Free Software
  31. ;   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  32.  
  33. ;
  34. ;  Structure elements specific to the AT&T T7231 chip
  35. ;
  36.  
  37. ; System Configuration Pointer
  38. scp_struc    struc
  39. scp_bus        db    ?,?,?, ?,?,?    ; bus use flag (0=16 bit, 1=8 bit).
  40. scp_ptr        dd    ?        ; 24pointer to iscp
  41. scp_struc    ends
  42.  
  43. ; Intermediate System Configuration Pointer
  44. iscp_struc    struc
  45. iscp_busy    db    ?,?        ; busy flag (zeroed after init).
  46. iscp_offset    dw    ?        ; 16pointer to iscp
  47. iscp_base    dd    ?        ; base for all 16 pointers, lo, hi
  48. iscp_struc    ends
  49.  
  50. ; System Control Block
  51. scb_struc    struc
  52. scb_stat    dw    ?        ; status
  53. scb_com        dw    ?        ; command
  54. scb_cbl        dw    ?        ; 16pointer to command block list
  55. scb_rfa        dw    ?        ; 16pointer to receive frame list
  56. scb_serrs    dw    4 dup(?)    ; 4 words of error counts
  57. scb_struc    ends
  58.  
  59. ; (Received) Frame Descriptor
  60. fd_struc    struc
  61. fd_status    dw    ?        ; status word for frame
  62. fd_eol        dw    ?        ; end of FD list flag
  63. fd_link        dw    ?        ; 16pointer to next FD
  64. fd_ptr        dw    ?        ; 16pointer to list of RBD's
  65. fd_dest        db    EADDR_LEN dup(?); 48 bits of destination
  66. fd_source    db    EADDR_LEN dup(?); 48 bits of source
  67. fd_cnt        dw    ?        ; length field of frame.
  68. fd_struc    ends
  69.  
  70. ; Receive Buffer Descriptor
  71. rbd_struc    struc
  72. rbd_status    dw    ?        ; status word in RBD
  73. rbd_link    dw    ?        ; 16pointer to next RBD
  74. rbd_ptr        dd    ?        ; 24pointer to actual buffer
  75. rbd_size    dw    ?        ; size of the buffer
  76. rbd_struc    ends
  77.  
  78. ; Transmit Command Block
  79. tcb_struc    struc
  80. tcb_status    dw    ?        ; status word for xmit
  81. tcb_com        dw    ?        ; command to transmit
  82. tcb_link    dw    ?        ; 16pointer to next command
  83. tcb_ptr        dw    ?        ; 16pointer to xmit TBD
  84. tcb_addr    db    EADDR_LEN dup(?); destination address
  85. tcb_len        dw    ?
  86. tcb_struc    ends
  87.  
  88. ; Transmit Buffer Descriptor
  89. tbd_struc    struc
  90. tbd_status    dw    ?        ; bit 15=EOF, 13-0=actual count
  91. tbd_link    dw    ?        ; 16pointer to next TBD
  92. tbd_ptr        dd    ?        ; 24pointer to buffer
  93. tbd_struc    ends
  94.  
  95. ; all commands have at least the following:
  96. cmd_struc    struc
  97. cmd_status    dw    ?        ; status word
  98. cmd_com        dw    ?        ; command word.
  99. cmd_struc    ends
  100.  
  101. ; MC-SETUP Command Block
  102. mcb_struc    struc
  103. mcb_status    dw    ?        ; status word for multicast
  104. mcb_com        dw    ?        ; command to setup multicast
  105. mcb_link    dw    ?        ; 16pointer to next command
  106. mcb_cnt        dw    ?        ; number of multicast addresses.
  107. mcb_struc    ends
  108.  
  109.  
  110. ;Memory allocation.
  111.  
  112. ;SCPTR    EQU    0fff6h            ; hardwired address for SCP
  113. ;ISCPTR    EQU    0ffeeh            ; my address for ISCP, points to SCB
  114. SCPTR    EQU    03ff6h            ; hardwired address for SCP
  115. ISCPTR    EQU    03feeh            ; my address for ISCP, points to SCB
  116. SCB    EQU    ISCPTR - 16        ; system control block base
  117. CCBPTR    EQU    SCB - 18        ; offset of configure command block
  118. TBDPTR    EQU    CCBPTR - 8        ; xmit BD offset
  119. TCBPTR    EQU    TBDPTR - 16        ; xmit CB offset
  120. TBUFPTR    EQU    TCBPTR - GIANT        ; xmit buffer offset
  121. ;the receive buffers appear at lower addresses than TBUFPTR.
  122. RBUFLEN    EQU    200
  123. RBUF_TOTAL    equ    (size fd_struc) + (size rbd_struc) + RBUFLEN
  124. FDBASE        equ    TBUFPTR - RBUF_TOTAL
  125.  
  126. memory_begin    dw    ?
  127.  
  128.     public    rcv_modes
  129. rcv_modes    dw    7        ;number of receive modes in our table.
  130.         dw    0               ;There is no mode zero
  131.         dw    0
  132.         dw    rcv_mode_2
  133.         dw    rcv_mode_3
  134.         dw    rcv_mode_4    ;haven't set up perfect filtering yet.
  135.         dw    0
  136.         dw    rcv_mode_6
  137.  
  138. firstfd        dw    FDBASE        ; start of FD queue
  139. lastfd        dw    0        ; end of the FD chain
  140. lastbd        dw    0        ; end of the BD chain
  141. flag        dw    0
  142.  
  143.  
  144. ;
  145. ; Configuration block for 82586, this comprises one config command
  146. ;  Parameters taken from MICOM driver
  147. ;
  148. CBCONF    DW    0        ; status word
  149.     DW    8002H        ; end of command list + configure command
  150.     DW    0ffffh        ; link to next command (not used)
  151.     DW    080CH        ; fifo=8, byte count=C
  152.     DW    2E00H        ; important! Addr (AL) not inserted on the fly!
  153.     DW    6000H        ; IFS = 60h
  154.     DW    0F200H        ; retry=F, slot time=200h
  155. CBCONF_FLAGS    label    byte
  156.     DW    0        ; flags, set to 1 for promiscuous
  157. CBCONF_MINLEN    label    byte
  158.     DW    40H        ; min frame length=40h
  159.  
  160.  
  161. doca_wait:
  162. ;enter with ax = command to execute, es = base_addr.
  163. ;exit with nc if the command ran to completion.
  164. ;exit with cy if the command timed out.  Eventually we'll also reset the chip.
  165.     mov    es:[SCB].scb_com,ax    ;set the command.
  166.  
  167.     mov    si,es:[SCB].scb_cbl    ;
  168.     mov    es:[si].cmd_status,0    ; status word of specific command
  169.     and    ax,0700h
  170.     cmp    ax,0100h        ; is it an action command?
  171.     jne    doca_wait_a        ; no, any other
  172.  
  173.     call    doca
  174.  
  175. comment \
  176. Quoting from the D-Step Errata Revision 2.0:
  177.  
  178. The value for the deadman timer should be greater than the longest
  179. command execution time.  The command which can take the longest time
  180. to execute is the transmit command, assuming maximum retries.  To
  181. determine the maximum amount of time the transmit command may take,
  182. one must use the following equation: 7143 ST + 14 f, where ST stands
  183. for Slot Time and f = Maximum Frame Size + IFS + Preamble.  For
  184. Ethernet/IEEE 802.3 where ST = 512 bits, f = 12144 bits, Preamble =
  185. 64 bits, IFS  96 bits, and one bit = 0.1 usec, the deadman timeout
  186. should be greater than 0.369 seconds.
  187.  
  188. \
  189.  
  190.     mov    ax,14            ;36.4 ticks / seconds * .369 seconds
  191.     call    set_timeout
  192. doca_wait_1:
  193.     test    es:[si].cmd_status,8000h    ; is command complete?
  194.     jnz    doca_wait_2        ;yes.
  195.     call    do_timeout        ;did we time out yet?
  196.     jne    doca_wait_1        ;not yet.
  197. ;reset the chip here, then Configure, IA-Setup, and MC-Setup.
  198.     stc                ;timeout -- uh-oh.
  199.     ret
  200. doca_wait_2:
  201.     clc
  202.     ret
  203.  
  204. doca_wait_a:
  205.     call    doca
  206. doca_wait_a_0:
  207.     cmp    es:[SCB].scb_com,0    ; has the command been accepted?
  208.     jnz    doca_wait_a_0        ; not yet.
  209.     clc
  210.     ret
  211.  
  212.  
  213.     include    timeout.asm
  214.     include    movemem.asm
  215.  
  216.     public    as_send_pkt
  217. ; The Asynchronous Transmit Packet routine.
  218. ; Enter with es:di -> i/o control block, ds:si -> packet, cx = packet length,
  219. ;   interrupts possibly enabled.
  220. ; Exit with nc if ok, or else cy if error, dh set to error number.
  221. ;   es:di and interrupt enable flag preserved on exit.
  222. as_send_pkt:
  223.     ret
  224.  
  225.     public    drop_pkt
  226. ; Drop a packet from the queue.
  227. ; Enter with es:di -> iocb.
  228. drop_pkt:
  229.     assume    ds:nothing
  230.     ret
  231.  
  232.     public    xmit
  233. ; Process a transmit interrupt with the least possible latency to achieve
  234. ;   back-to-back packet transmissions.
  235. ; May only use ax and dx.
  236. xmit:
  237.     assume    ds:nothing
  238.     ret
  239.  
  240.  
  241.     public    send_pkt
  242. send_pkt:
  243. ;enter with es:di->upcall routine, (0:0) if no upcall is desired.
  244. ;  (only if the high-performance bit is set in driver_function)
  245. ;enter with ds:si -> packet, cx = packet length.
  246. ;exit with nc if ok, or else cy if error, dh set to error number.
  247.     assume    ds:nothing
  248.     mov    es,base_addr        ; base for board
  249.  
  250.     cmp    cx,GIANT        ; Is this packet too large?
  251.     ja    send_pkt_toobig
  252.  
  253.     mov    dx,cx            ; save a copy, might be less than 60, ok
  254.  
  255.     cmp    dx,RUNT            ; minimum length for Ether
  256.     jnb    oklen
  257.     mov    dx,RUNT            ; make sure size at least RUNT
  258. oklen:
  259.     mov    di,TBUFPTR        ; start of xmit buffer
  260.  
  261. ;
  262. ;  check for previous xmit
  263. ;
  264. xwait:
  265.     mov    bx,es:[SCB].scb_com    ; has previous command been accepted?
  266.     or    bx,bx
  267.     jnz    xwait            ; not there yet, wait for it
  268. wait_for_transmit_to_complete:
  269.     test    word ptr es:[TCBPTR],4000h
  270.     jnz    wait_for_transmit_to_complete
  271. ;
  272. ;  move the data using word moves.
  273. ;
  274.     call    movemem
  275. ;
  276. ;  put the correct size into the TBD
  277. ;
  278.     or    dx,08000h            ; end of frame bit flag
  279.     mov    es:[TBDPTR].tbd_status,dx    ; store it
  280.     mov    es:[TCBPTR].tcb_status,0    ; zero status wd
  281.     mov    es:[TCBPTR].tcb_com,8004h    ; xmit command in TCB
  282.     mov    es:[SCB].scb_com,0100h        ; execute command
  283.     mov    es:[SCB].scb_cbl,TCBPTR    ; say where xmit command is
  284.  
  285.     call    doca
  286.  
  287.     clc
  288.     ret
  289. send_pkt_toobig:
  290.     mov    dh,NO_SPACE
  291.     stc
  292.     ret
  293.  
  294.  
  295. rcv_mode_2:
  296.     and    CBCONF_FLAGS,not 3
  297.     or    CBCONF_FLAGS,2        ;disable broadcasts.
  298.     mov    CBCONF_MINLEN,40h
  299.     jmp    short reconfigure
  300. rcv_mode_4:
  301. rcv_mode_3:
  302.     and    CBCONF_FLAGS,not 3    ;clear promiscuous mode.
  303.     mov    CBCONF_MINLEN,40h
  304.     jmp    short reconfigure
  305. rcv_mode_6:
  306.     and    CBCONF_FLAGS,not 3
  307.     or    CBCONF_FLAGS,1        ;set promiscuous mode.
  308.     mov    CBCONF_MINLEN,0        ;allow runts.
  309. reconfigure:
  310.     mov    es,base_addr        ;get the base address for the board.
  311.     mov    si,offset CBCONF    ; configure command
  312.     mov    di,CCBPTR        ; where command will reside
  313.     mov    cx,9
  314.     rep    movsw            ; copy to board
  315. ;
  316. ;  issue the configure command
  317. ;
  318.     mov    es:[SCB].scb_cbl,CCBPTR    ; where conf command is
  319.     mov    es:[SCB].scb_serrs[0],0    ; zero errs field
  320.     mov    es:[SCB].scb_serrs[2],0    ; zero errs field
  321.     mov    es:[SCB].scb_serrs[4],0    ; zero errs field
  322.     mov    es:[SCB].scb_serrs[6],0    ; zero errs field
  323.     mov    ax,100h            ; do-command command
  324.     call    doca_wait
  325.     ret
  326.  
  327.  
  328.     public    set_multicast_list
  329. set_multicast_list:
  330. ;enter with ds:si ->list of multicast addresses, cx = number of addresses.
  331. ;return nc if we set all of them, or cy,dh=error if we didn't.
  332.     assume    ds:code
  333.     mov    es,base_addr
  334.     mov    es:[SCB].scb_cbl,TBUFPTR    ;use the transmit buffer.
  335.  
  336.     mov    es:[TBUFPTR].mcb_status,0    ;status word
  337.     mov    es:[TBUFPTR].mcb_com,08003h    ;command word for mc-setup + EL
  338.     mov    es:[TBUFPTR].mcb_link,-1    ;no command link.
  339.     mov    di,TBUFPTR + mcb_cnt
  340.     mov    ax,cx            ;store the count.
  341.     stosw
  342.     rep    movsb
  343.  
  344. comment \ avoid deferred execution of a CU command during reception.
  345. If a command is executed with a length of 18 to 20 bytes, and a frame
  346. is received, the 82586 may deadlock with HOLD active.  We avoid this
  347. problem by suspending the receiver. \
  348.  
  349.     mov    ax,30h            ;suspend frame receiving.
  350.     call    doca_wait
  351.  
  352.     mov    ax,100h            ; do-command command
  353.     call    doca_wait
  354.     jnc    set_multicast_2
  355.  
  356.     mov    ax,20h            ;resume frame receiving.
  357.     call    doca_wait
  358.  
  359.     mov    dh,NO_MULTICAST        ;for some reason we can't do multi's.
  360.     stc
  361.     ret
  362. set_multicast_2:
  363.     mov    ax,20h            ;resume frame receiving.
  364.     call    doca_wait
  365.  
  366.     clc
  367.     ret
  368.  
  369.  
  370.     public    terminate
  371. terminate:
  372.     assume    ds:code
  373.     ret
  374.  
  375.     public    reset_interface
  376. reset_interface:
  377. ;reset the interface.
  378. ;we don't do anything.
  379.     assume    ds:nothing
  380. retpoint:
  381.     ret
  382.  
  383.  
  384. ;called when we want to determine what to do with a received packet.
  385. ;enter with cx = packet length, es:di -> packet type, dl = packet class.
  386.     extrn    recv_find: near
  387.  
  388. ;called after we have copied the packet into the buffer.
  389. ;enter with ds:si ->the packet, cx = length of the packet.
  390.     extrn    recv_copy: near
  391.  
  392.     extrn    count_in_err: near
  393.     extrn    count_out_err: near
  394.  
  395.     public    recv
  396. recv:
  397.   ifdef IO_INTCLR
  398.     loadport            ;clear the interupt latch.
  399.     setport    IO_INTCLR
  400.     out    dx,al
  401.   endif
  402.  
  403.     mov    flag, 1
  404. ;called from the recv isr.  All registers have been saved, and ds=cs.
  405. ;Upon exit, the interrupt will be acknowledged.
  406. recv1:
  407.     mov    ds,base_addr    ; base for board
  408.     assume    ds:nothing
  409.  
  410.     mov    ax,ds:[SCB].scb_stat    ;get the status.
  411. recv_isr_1:
  412.     cmp    ds:[SCB].scb_com,0    ;has previous command been accepted?
  413.     jne    recv_isr_1        ;no -- keep waiting.
  414.  
  415.     and    ax,0f000h        ;isolate the ACK bits to make a
  416.                     ;  command to ack the interrupt.
  417.   if DAN and 1
  418.     jz    recv_isr_2
  419.   endif
  420.  
  421.     mov    ds:[SCB].scb_com,ax    ;set the command.
  422.     call    doca
  423. recv_isr_2:
  424.     cmp    ds:[SCB].scb_com,0    ; has the command been accepted?
  425.     jnz    recv_isr_2        ; not yet.
  426.  
  427. ;  Get whatever packets are on the board
  428. ;
  429.     mov    bx,firstfd    ; get addr of first FD in list
  430.     mov    ax,[bx].fd_status    ; status word of frame
  431.     test    ax,08000h    ; frame written?
  432.     jnz    okframe
  433.  
  434.     jmp    ru_start    ; no, restore receiver if necessary
  435. frame_bad:
  436.     call    count_in_err
  437. ptrupdate_j_1:
  438.     jmp    ptrupdate
  439.  
  440. ;  we have a frame, read it in
  441. ;
  442. okframe:
  443.     test    ax,02000h        ;check frame OK bit
  444.     jz    frame_bad        ;bad, fix it.
  445.     mov    si,[bx].fd_ptr        ;get pointer to buffer descriptor
  446.     xor    cx,cx            ;start with zero bytes.
  447. countbuf:                ;es:di is already set to receive packet
  448.     mov    dx,si            ;save a copy of current BD ptr
  449.     mov    ax,[si].rbd_status    ;get status and count word for BD
  450.     test    ax,04000h        ;is count field there?
  451.     jz    ptrupdate_j_1        ;no - we give up here.
  452.     add    cl,al            ;add the count into cx.
  453.     adc    ch,0
  454.     mov    si,[si].rbd_link    ;go to next BD in list
  455.     test    ax,8000h        ;is this the last frame?
  456.     je    countbuf        ;no - keep counting.
  457.  
  458.     push    bx
  459.     push    cx
  460.  
  461.     mov    ax,cs            ;we need ds = code.
  462.     mov    ds,ax
  463.     assume    ds:code
  464.  
  465.     mov    es,base_addr        ;get a pointer to their type.
  466.     mov    di,es:[bx].fd_ptr    ;get pointer to buffer descriptor
  467.     mov    di,es:[di].rbd_ptr.offs    ;get offset of data
  468.     add    di,EADDR_LEN+EADDR_LEN    ;skip the ethernet addreses and
  469.                     ;  point to the packet type.
  470.  
  471.     mov    dl, BLUEBOOK        ;assume bluebook Ethernet.
  472.     mov    ax, es:[di]
  473.     xchg    ah, al
  474.     cmp     ax, 1500
  475.     ja    BlueBookPacket
  476.     inc    di            ;set di to 802.2 header
  477.     inc    di
  478.     mov    dl, IEEE8023
  479. BlueBookPacket:
  480.     call    recv_find        ;look up our type.
  481.  
  482.     pop    cx
  483.     pop    bx
  484.     mov    ds,base_addr        ;restore ds to the board.
  485.     assume    ds:nothing
  486.  
  487.     mov    ax,es            ;is this pointer null?
  488.     or    ax,di
  489.     je    ptrupdate        ;yes - just free the frame.
  490.  
  491.     push    cx
  492.     push    es            ;remember where the buffer pointer is.
  493.     push    di
  494.   if DAN and 2
  495.     push    cx
  496.   endif
  497.  
  498.     mov    si,[bx].fd_ptr        ;get pointer to buffer descriptor
  499. copybuf:
  500.     mov    dx,si            ;save a copy of current BD ptr
  501.     xor    ch,ch            ;200 bytes is largest this can be
  502.     mov    cl,byte ptr [si].rbd_status;get count word for BD
  503.     mov    si,[si].rbd_ptr.offs    ;get offset of data
  504.   if DAN and 2
  505.     pop    ax
  506.     sub    ax, cx
  507.     jc    copydone
  508.     push    ax
  509.   ENDIf
  510.     call    movemem
  511.     mov    si,dx            ;get back current BD ptr
  512.     test    [si].rbd_status,8000h    ;check EOF bit
  513.     mov    si,[si].rbd_link    ;go to next BD in list
  514.     jz    copybuf            ;not done, keep copying it.
  515.  
  516.   if DAN and 2
  517.     pop    cx
  518. copydone:
  519.   endif
  520.     pop    si            ;now give the frame to the client.
  521.     pop    ds
  522.     pop    cx
  523.     assume    ds:nothing
  524.  
  525.     call    recv_copy
  526. ;
  527. ;  we are done with the frame, do the list management
  528. ;
  529. ptrupdate:
  530.     push    cs
  531.     pop    ds
  532.     assume    ds:code
  533.     mov    es,base_addr        ; reload board segment
  534.  
  535.     mov    si,es:[bx].fd_ptr    ; first BD in frame list
  536. nextbd:
  537.     mov    cx,es:[si].rbd_status    ; count word for BD, EOF bit
  538.     test    cx,08000h        ; EOF bit, if set, save si in lastbd
  539.     jnz    dolastbd
  540.     mov    es:[si].rbd_status,0    ; clear status word, EOF bit
  541.     cmp    si,lastbd        ; see if we are wrapping
  542.     jz    dolastbd        ; yes, just undo it
  543.     mov    si,es:[si].rbd_link    ; follow link
  544.     jmp    nextbd
  545. dolastbd:
  546.     mov    di,lastbd        ; where end of BD list is now
  547.     mov    lastbd,si        ; store last known BD
  548.     mov    es:[si].rbd_size,08000h+200; end of list here
  549.     mov    es:[si].rbd_status,0    ; clear status word, EOF bit
  550. ; size field for not end of list
  551.     mov    es:[di].rbd_size,200    ; remove old end-of-list
  552.  
  553. ;
  554. ;  update the FD list flags, new end-of-list
  555. ;
  556.     mov    es:[bx].fd_eol,08000h    ; store new EOL
  557.     mov    es:[bx].fd_status,0    ; clear status word for frame
  558.     mov    di,lastfd        ; get old end-of-list
  559.     mov    es:[di].fd_eol,0    ; zero old one
  560.     mov    lastfd,bx        ; update stored pointer
  561.     mov    si,es:[bx].fd_link    ; where next fd is
  562.     mov    firstfd,si        ; store that info for next time
  563.   if DAN and 4
  564.     jmp    recv1
  565.   endif
  566.  
  567. ru_start:
  568. ; re-start receive unit
  569. ;
  570. ;  check to see if the receiver went off because of no resources
  571. ;  and restart receiver if necessary
  572. ;
  573.     push    cs
  574.     pop    ds
  575.     mov    es,base_addr
  576.     mov    ax,es:[SCB].scb_stat    ; status word for SCB
  577.     and    ax,070h        ; receiver status
  578.     cmp    al,020h        ; receiver has no resources
  579.     jnz    hasres
  580.   if DAN and 8
  581.     cmp    flag, 1
  582.     jnz    ru_start1
  583.     mov    flag, 0
  584.     jmp    recv1
  585.   endif
  586.  
  587. ru_start1:
  588.     call    count_out_err
  589. ;
  590. ;  setup lists for starting the RU on the chip
  591. ;  we know that there isn't anything in the buffer that we want
  592. ;
  593.  
  594.     mov    bx,firstfd        ; get first FD on free list (assume free)
  595.     mov    es:[SCB].scb_rfa,bx    ; put into SCB
  596.     mov    si,lastbd        ; pointer to a BD, end of chain
  597.     mov    ax,es:[si].rbd_link    ; pointer to next BD
  598.     mov    es:[bx].fd_ptr,ax    ; set to start of BDs
  599. ;
  600. ;
  601. ;  Start the RU, doesn't need CB, only SCB parms.
  602. ;   command, to start receiving again
  603. ;
  604.     mov    ax,10h            ; start RU
  605.     call    doca_wait
  606. hasres:
  607. ;I don't we need to wait here because we haven't done anything to wait for.
  608.     ret
  609.  
  610.  
  611.     public    recv_exiting
  612. recv_exiting:
  613. ;called from the recv isr after interrupts have been acknowledged.
  614. ;Only ds and ax have been saved.
  615.     assume    ds:nothing
  616.     ret
  617.  
  618.  
  619.     public    set_address
  620. set_address:
  621.     assume    ds:nothing
  622. ;enter with ds:si -> Ethernet address, CX = length of address.
  623. ;exit with nc if okay, or cy, dh=error if any errors.
  624.     cmp    cx,EADDR_LEN        ;ensure that their address is okay.
  625.     je    set_address_4
  626.     mov    dh,BAD_ADDRESS
  627.     stc
  628.     jmp    short set_address_done
  629. set_address_4:
  630.  
  631. ;  Next step, load our address into the board
  632. ;     reuses the space that the configure command used, with different command
  633. ;
  634.     mov    es,base_addr        ; set to base address
  635.     mov    es:[SCB].scb_cbl,CCBPTR    ; say where conf command is
  636.  
  637.     mov    di,CCBPTR        ; start of config command block
  638.     xor    ax,ax
  639.     stosw                ; zero status word for commmand
  640.     mov    ax,8001h        ; IA setup command + EL
  641.     stosw
  642.     xor    ax,ax
  643.     dec    ax
  644.     stosw                ; set link value to -1 (unused)
  645.  
  646.     rep    movsb            ; move their ethernet address in.
  647. ;
  648. ;  start the IA setup command
  649. ;
  650.     mov    ax,100h            ; do-command command
  651.     call    doca_wait
  652.     jnc    set_address_okay
  653.     mov    dh,-1            ; no error in the list applies.
  654.     jmp    short set_address_done
  655. set_address_okay:
  656.     mov    cx,EADDR_LEN        ;return their address length.
  657.     clc
  658. set_address_done:
  659.     push    cs
  660.     pop    ds
  661.     assume    ds:code
  662.     ret
  663.  
  664.  
  665. end_resident    label    byte
  666.  
  667. timeout_msg    db    "Timed out while initializing the board.",CR,LF,'$'
  668. security_msg db    "Security is enabled.  Do not attempt to change "
  669.              db "the ethernet address or",CR,LF
  670.              db "set promiscuous mode on this board.  Unexpected results "
  671.              db "may occur.",CR,LF,'$'
  672.  
  673. our_address    db    6 dup(?)    ;temporarily hold our address
  674.  
  675.  
  676. mem8_16        db    2        ; 1 for 16k, 2 for 8k
  677.  
  678.     extrn    set_recv_isr: near
  679.     extrn    maskint: near
  680.  
  681. ;enter with si -> argument string, di -> word to store.
  682. ;if there is no number, don't change the number.
  683.     extrn    get_number: near
  684.  
  685. ;enter with dx -> name of word, di -> dword to print.
  686.     extrn    print_number: near
  687.  
  688. ;enter with ax = number to print.
  689.     extrn    decout: near
  690.  
  691. timeout_error:
  692.     mov    dx,offset timeout_msg
  693.     jmp    short error
  694. error:
  695.     mov    ah,9
  696.     int    21h
  697.     stc
  698.     ret
  699.  
  700. ;
  701. ;  data for configuring and setting up the board
  702. ;
  703. ;  chip always looks at SCP for config info which points to ISCP for the
  704. ;  pointer to the CONTROL BLOCK which handles everything from there.
  705. ;  Kind of indirect, but it works.
  706. ;
  707. SCP    DB    0            ; bus use flag (0=16 bit, 1=8 bit).
  708.  
  709.     public    etopen
  710. etopen:
  711.     mov    al,int_no
  712.     call    maskint            ;disable these interrupts.
  713.  
  714. ;  Initialize the Ethernet board, set receive type.
  715. ;
  716.     mov        es,base_addr
  717. ;
  718. ;    Check for the ATTLAN signature in shared memory
  719. ;
  720.     mov        di,3ff9h
  721.     cmp        byte ptr es:[di],'A'
  722.     jnz        no_sig
  723.     inc        di
  724.     cmp        byte ptr es:[di],'T'
  725.     jnz        no_sig
  726.     inc        di
  727.     cmp        byte ptr es:[di],'T'
  728.     jnz        no_sig
  729.     inc        di
  730.     cmp        byte ptr es:[di],'L'
  731.     jnz        no_sig
  732.     inc        di
  733.     cmp        byte ptr es:[di],'A'
  734.     jnz        no_sig
  735.     inc        di
  736.     cmp        byte ptr es:[di],'N'
  737.     jnz        no_sig
  738.     mov        di,io_addr
  739.     shr        di,1
  740.     shr        di,1
  741.     shr        di,1
  742.     shr        di,1
  743.     and        di,001fh
  744.     mov        es:[3fffh],di
  745. no_sig:
  746.  
  747. ;
  748. ;  check for correct EPROM location
  749. ;
  750.     call    check_board
  751.  
  752. ;
  753. ;  Turn off interrupts, I don't want them
  754. ;
  755.   ifdef IOINTOF
  756.     loadport
  757.     setport IOINTOF
  758.     out    dx,al
  759.   endif
  760. ;
  761. ;  Disconnect from network
  762. ;
  763.   ifdef IODIS
  764.     loadport
  765.     setport    IODIS
  766.     out    dx,al
  767.   endif
  768.  
  769. ;
  770. ;  Initialize the Ethernet board.
  771. ;
  772.     sub    base_addr,0e00h
  773.     mov    di,0e000h        ;our initial base address.
  774.     mov    si,ISCPTR-2        ;try the init down a little.
  775.  
  776. ;
  777. ;  Now discern the end of memory by repeatedly re-initializing the board
  778. ;  until the BUSY flag in the ISCP gets reset.
  779. ;
  780. re_discern:
  781.     mov    es,base_addr        ;remember where we think it starts.
  782.     call    init_root        ;did we find our memory size?
  783.     jc    confng            ;no, keep trying.
  784.     inc    si            ;yes, see if we found the real one.
  785.     inc    si
  786.     call    init_root        ;try initializing it in a different locn.
  787.     jnc    confok            ;it worked!  we've found the root.
  788.     dec    si            ;it didn't work, keep trying.
  789.     dec    si
  790. confng:
  791.     or    di,di            ;did we try all 64K?
  792.     je    confbad            ;yes.
  793.  
  794.     add    base_addr,200h        ;advance the segment by 2000h bytes.
  795.     sub    di,2000h        ;retreat the offset by 2000h bytes.
  796.     jmp    re_discern        ;try this next higher address.
  797. confbad:
  798.     sti
  799.     jmp    timeout_error
  800.  
  801. confok:
  802.     mov    memory_begin,di
  803.     call    reconfigure
  804.     jc    confbad
  805. ;  
  806. ;  We have to determine if security is enabled on the board.  This is done by
  807. ;  attempting to set the board into promiscuous mode (rcv_mode_6).  We will
  808. ;  then check to see if the "Command Abort" bit has been set.  If it has, then
  809. ;  security is enabled and we will notify the user.
  810. ;
  811.     call    rcv_mode_6
  812.     jc        confbad
  813.     test    es:[CCBPTR].cmd_status,01000h
  814.     jz        no_security
  815.     mov        dx,offset security_msg
  816.     mov        ah,9
  817.     int        21h
  818.     mov        word ptr rcv_modes+14,0000h
  819. no_security:
  820.     call    rcv_mode_3
  821.     jc        confbad
  822. ;
  823. ;  Ask the board for the Ethernet address, and then use set_address to set it.
  824. ;
  825.     push    ds
  826.     pop    es
  827.     mov    di,offset our_address
  828.     mov    cx,EADDR_LEN
  829.     call    get_address
  830.  
  831.     mov    si,offset our_address
  832.     mov    cx,EADDR_LEN
  833.     call    set_address
  834.     jnc    store_address_2
  835.     sti
  836.     jmp    timeout_error
  837. store_address_2:
  838. ;
  839. ;  IA sent, setup all of the other data structures on the board
  840. ;  start with xmit command descriptors
  841. ;
  842.     mov    di,TCBPTR
  843.     mov    es:[di].tcb_status,0
  844.     mov    es:[di].tcb_com,08004h
  845.     mov    es:[di].tcb_link,-1
  846.     mov    es:[di].tcb_ptr,TBDPTR
  847.  
  848.     add    di,(size tcb_struc)
  849.  
  850.     mov    es:[di].tbd_status,0
  851.     mov    es:[di].tbd_link,0
  852.     mov    es:[di].tbd_ptr.offs,TBUFPTR
  853.     mov    es:[di].tbd_ptr.segm,0
  854.  
  855. ; Note that we allocate fd's, rbd's, and buffers all at the same time.  This
  856. ; doesn't mean that each pair of fd's and rbd's necessarily have anything to
  857. ; do with each other.  We just allocate them together because we want to have
  858. ; the same number of each, and it's easier to compute that way.
  859.  
  860.     mov    di,TBUFPTR        ;get the last buffer.
  861.  
  862.     mov    ax,di            ;compute the amount of free memory.
  863.     sub    ax,memory_begin
  864.     xor    dx,dx
  865.     mov    bx,RBUF_TOTAL        ;each buffer takes this much.
  866.     div    bx
  867.     mov    cx,ax            ;put the number of buffers into cx.
  868.  
  869. init_rbuff_0:
  870.     sub    di,RBUF_TOTAL        ;back the pointer down by a little.
  871.  
  872. ;init the FD.
  873.     mov    es:[di].fd_status,0
  874.     mov    es:[di].fd_eol,0
  875.     mov    es:[di].fd_ptr,-1
  876.     lea    ax,[di]-RBUF_TOTAL    ;get the address of the next buffer.
  877.     mov    es:[di].fd_link,ax
  878.  
  879. ;init the BD.
  880.     lea    bx,[di + (size fd_struc)]
  881.     mov    es:[bx].rbd_status,0
  882.     lea    ax,[bx-RBUF_TOTAL]    ;make a pointer to the next BD
  883.     mov    es:[bx].rbd_link,ax
  884.     lea    ax,[bx+(size rbd_struc)]    ;make a pointer to the buffer.
  885.     mov    es:[bx].rbd_ptr.offs,ax
  886.     mov    es:[bx].rbd_ptr.segm,0
  887.     mov    es:[bx].rbd_size,RBUFLEN    ;length of the buffer.
  888.  
  889.     loop    init_rbuff_0
  890.  
  891. init_rbuff_1:
  892. ;patch the parameters of the last FD and BD so they link around to the head.
  893.     mov    es:[di].fd_eol,8000h
  894.     mov    es:[di].fd_link,FDBASE
  895.     mov    lastfd,di
  896.  
  897.     lea    bx,[di + (size fd_struc)]
  898.     mov    es:[bx].rbd_link,FDBASE + (size fd_struc)
  899.     mov    es:[bx].rbd_size,RBUFLEN + 8000h
  900.     mov    lastbd,bx
  901.  
  902. ;now put the location of the first rbd into the first fd.
  903.     mov    es:[FDBASE].fd_ptr,FDBASE  + (size fd_struc)
  904.  
  905.     call    enable_network
  906.  
  907. ;
  908. ;  Start the RU, doesn't need CB, only SCB parms.
  909. ;   command, to start receiving
  910. ;
  911.     mov    es:[SCB].scb_rfa,FDBASE    ; set to frame descriptors
  912.     mov    ax,10h            ; start RU
  913.     call    doca_wait
  914. ;
  915. ; Now reset CX, FR, CNA, and RNR so that we don't get a spurious interrupt.
  916. ;
  917.     mov    ax,es:[SCB].scb_stat    ;get the status.
  918.     and    ax,0f000h        ;isolate the ACK bits.
  919.     mov    es:[SCB].scb_com,ax    ;make a command to
  920.                     ;acknowledge the interrupt.
  921.     call    doca
  922. ;
  923. ; Now hook in our interrupt
  924. ;
  925.     call    set_recv_isr
  926.  
  927.     sti
  928.  
  929.     mov    al, int_no        ; Get board's interrupt vector
  930.     add    al, 8
  931.     cmp    al, 8+8            ; Is it a slave 8259 interrupt?
  932.     jb    set_int_num        ; No.
  933.     add    al, 70h - 8 - 8        ; Map it to the real interrupt.
  934. set_int_num:
  935.     xor    ah, ah            ; Clear high byte
  936.     mov    int_num, ax        ; Set parameter_list int num.
  937.  
  938.     mov    dx,offset end_resident
  939.     clc
  940.     ret
  941.  
  942.  
  943. init_root:
  944. ;enter with es:di -> beginning of our system memory window,
  945. ;  si -> place to put ISC.
  946. ;exit with nc if it worked, cy if it didn't work.
  947.  
  948.     mov    al,SCP
  949.     mov    es:[SCPTR].scp_bus,al
  950.     mov    es:[SCPTR].scp_ptr.offs,si
  951.     mov    es:[SCPTR].scp_ptr.segm,0
  952.  
  953.     mov    es:[si].iscp_busy,1        ;set busy bit.
  954.     mov    es:[si].iscp_offset,SCB        ;point to the SCB.
  955.     mov    es:[si].iscp_base.offs,0    ;scb base.
  956.     mov    es:[si].iscp_base.segm,0    ;scb base.
  957.  
  958.     call    reset_586        ; reset the 586, hardware-specific.
  959.  
  960.     mov        al,int_no
  961.     cmp        al,2
  962.     jnz        int_not2
  963.     mov        al,9
  964. int_not2:
  965.     loadport
  966.     setport    IOINTR
  967.     out        dx,al
  968.  
  969.     mov        al,08h
  970.     mov        ah,media_sel
  971.     or         ah,ah
  972.     jz        only_aui
  973.     add        al,04h
  974.     mov        ah,li_enabl
  975.     or        ah,ah
  976.     jz        tp_noli
  977.     add        al,02h
  978.  
  979. tp_noli:
  980. only_aui:
  981.     loadport
  982.     setport IOMISC
  983.     out dx,al
  984.  
  985.     mov        ax,1
  986.     call    set_timeout
  987. time_delay:
  988.     call    do_timeout
  989.     jne        time_delay
  990.  
  991. ;
  992. ;  Issue a CA to initialize the chip after reset
  993. ;
  994.     call    doca
  995.  
  996.     mov    ax,2            ;don't wait too long.
  997.     call    set_timeout
  998. init_root_2:
  999.     cmp    es:[si].iscp_busy,0    ;did it clear the busy flag?
  1000.     je    init_root_1        ;yes.
  1001.     call    do_timeout
  1002.     jne    init_root_2
  1003.     stc
  1004.     ret
  1005. init_root_1:
  1006.     clc
  1007.     ret
  1008.